import * as Cesium from 'cesium';
import log from './logs';

/**
 * 
 * @param {*} target 
 * @param {*} name 
 * @param {*} descriptor 
 * @returns 
 * @function PerformanceLog
 */
export function PerformanceLog(target, name, descriptor) {
    if (!descriptor || !descriptor.value) {
        throw new Error('Descriptor is undefined or descriptor.value is missing');
    };
    const originalMethod = descriptor.value;
    descriptor.value = async function (...args) {
        const start = performance.now();
        try {
            const result = await originalMethod.apply(this, args);
            const end = performance.now();
            log.debug(`${name} 方法执行耗时:${(end - start).toFixed(3)}ms`);
            return result;
        } catch (error) {
            log.error(`${name} 方法执行出错: `, error);
            throw error;
        }
    };
    return descriptor;
};

/**
 * 
 * @param {*} target 
 * @returns 
 * @function Add
 */
export function Add(target) {
    /**@abstract Unbind the lens */
    target.prototype.UnCamLookAt = function () {
        this._viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
    };
    return target;
};

/**
 * 
 * @param {*} target 
 * @param {*} name 
 * @param {*} descriptor 
 * @returns 
 * @function Overriding
 */
export function Overriding(target, name, descriptor) {
    if (!descriptor || !descriptor.value) {
        throw new Error('Descriptor is undefined or descriptor.value is missing');
    };
    /**@abstract class function name Overriding */
    descriptor.value = async function (...args) {
        log.debug(`${name}: Overriding!`);
        return new Promise((resolve, reject) => {
            this._viewer.camera.flyTo({
                destination: Cesium.Cartesian3.fromDegrees(
                    args[1],
                    args[2],
                    args[3]
                ),
                orientation: {
                    heading: Cesium.Math.toRadians(80.0),
                    pitch: Cesium.Math.toRadians(-90.0),
                },
                duration: 10,
                // flyOverLongitude: Cesium.Math.toRadians(60.0)
            });
            args[5]([args[0]]);
            this.CreateShowSwitchScene(args[4], () => {
                this._enCan.style.zIndex = 1;
                this._enCan.style.display = '';
            });
            resolve();
        });
    };
    return descriptor;
};

/**
 * 
 * @param {*} validator 
 * @returns 
 * @function Validate
 */
export function Validate(validator) {
    return function (target, propertyKey, descriptor) {
        if (!descriptor || !descriptor.value) {
            throw new Error('Descriptor is undefined or descriptor.value is missing');
        };
        const originalMethod = descriptor.value;
        descriptor.value = function (...args) {
            args.forEach((arg, index) => {
                if (!validator(arg)) {
                    throw new Error(
                        `Invalid argument ${propertyKey}, please input the correct parameters!`
                    );
                }
            });

            return originalMethod.apply(this, args);
        };

        return descriptor;
    };
};

/**
 * 
 * @param {*} target 
 * @param {*} propertyKey 
 * @param {*} descriptor 
 * @returns 
 * @function Center
 */
export function Center(target, propertyKey, descriptor) {
    if (!descriptor || !descriptor.value) {
        throw new Error('Descriptor is undefined or descriptor.value is missing');
    };
    const originalMethod = descriptor.value;
    descriptor.value = function (...args) {
        if (args[0].center === undefined || !args[0].center.length) throw new Error(
            `Invalid argument ${propertyKey}, please input the correct parameters!`
        );

        return originalMethod.apply(this, args);
    };

    return descriptor;
};